<!doctype html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Marked in the browser</title>
</head>
<body>
<div id="content"></div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
    document.getElementById('content').innerHTML = marked(`
    # Gitlab CI配置

为了更好的执行\`pipeline\`，自动化测试等手段提升软件质量，我们要求所有的仓库的根目录下新建\`.gitlab-ci.yml\`文件。如何配置仓库\`runner\`详见[这里](./register-runner.html)。

## 仓库范本

### Maven项目范本

.gitlab-ci.yml

\`\`\`yaml
stages:
  - build
  - unit
  - coverage
  - checkstyle

cache:
  paths:
    - "*/target/"
    - "target/"

build:
  stage: build
  script:
    - mvn clean package -U -Dmaven.test.skip=true -Dmaven.javadoc.skip=true

unit:
  stage: unit
  script:
    - mvn test

coverage:
  stage: coverage
  script:
    - coverageForJaCoCo

checkstyle:
  stage: checkstyle
  script:
    - mvn checkstyle:check
\`\`\`

如果想要静态代码扫描，可以把\`coverage\`替换掉，详见下面\`静态扫描\`部分。
### Web仓库范本

.gitlab-ci.yml

\`\`\`yaml
stages:
  - install_deps
  - lint
  - unit
  - build

cache:
  paths:
    - node_modules/
  policy: pull  # 只拉取缓存，不推送缓存。默认会即拉取，又推送。所以install_deps里需要覆盖此项。

# 安装依赖
install_deps:
  stage: install_deps
  retry: 2
  cache:
    paths:
      - node_modules/
  script:
    - npm install

# 运行代码检测
lint:
  stage: lint
  script:
    - npm run lint

# 运行unit单元测试
unit:
  stage: unit
  script:
    - npm run unit
  # 如果不使用静态扫描，可以注释下面cache
  cache:
    paths:
     - node_modules/
     - coverage/  # 单元测试生成的lcov文件的目录地址

build:
  stage: build
  script:
    - npm run build
\`\`\`

### 静态扫描

如果要启用静态扫描，在上面模板的\`stages\`中再增加一条：\`static_scan\`。

通用部分，先增加一个模板
\`\`\`yaml
# 静态扫描模板
.static_scan: &staticScanDef
  variables:
    GIT_DEPTH: "1"
  stage: static_scan
  retry:
    max: 2
    when:
      - runner_system_failure
      - stuck_or_timeout_failure
  only: # 分支这里可以按需求自行修改，不设置就代表每个分支都有
    - master
    - develop
\`\`\`

对于java项目：
\`\`\`yaml
# 静态扫描
static_scan:
  <<: *staticScanDef
  image: dk.uino.cn/sonar/maven:1.0.14
   cache:
    paths:
      - .sonar/cache
      - coverage
  script:
    # 后面添加\`-X\`，可以看到详细信息
    - kiss
\`\`\`

对于web项目，建议把它放在第一步，因为它与\`node\`没有依赖关系，这时请去除下面\`cache\`中\`node_modules\`。如果要在sonar应用上看到单元测试覆盖率，就配置到单元测试后。
\`\`\`yaml
# 静态扫描
static_scan:
  <<: *staticScanDef
  image: dk.uino.cn/sonar/scanner:1.0.14
  cache:
    paths:
      - .sonar/cache
      - coverage
      - node_modules
  script:
    # 扫描路径sonar.sources需要对应修改，也可以在根目录下新建sonar-project.properties文件配置，不过没有-D。
    # 后面的reportPaths是可选的，必须在上一步单元测试生成报告文件。如果配置了，就可以在sonar应用上看到单元测试覆盖率。
    # 再添加\`-X\`，可以看到详细信息
    - kiss -Dsonar.sources=src -Dsonar.typescript.lcov.reportPaths=coverage/lcov.info
  # allow_failure: true
\`\`\`

## 注意事项

以上范本只是标准范本，可根据自己的实际需求进行删改，更多\`.gitlab-ci.yml\`配置信息请看[这里](https://git.uino.com/help/ci/yaml/README.md)。

此外，有几点需要**额外注意**：

### 缓存配置

\`cache\`意思是缓存，建议添加缓存策略\`policy: pull\`，意思是只拉取缓存，不推送缓存。

默认策略是既拉取，又推送。所以在\`install_deps\`里需要覆盖此项，修改成默认的。

对于不需要使用缓存的任务，在单独任务里覆盖此项，把策略修改为\`push\`即可，也可以：\`cache: {}\`。

### npm登陆

\`install_deps\`这一步的\`script\`，需要要当前工程的\`CI/CD\`页面配置4个环境变量，详见[这篇](../npm/npm-login.html)。

### 克隆优化

如果工程比较大，\`clone\`时会把所有代码都下载下来，这样首次下拉就会很慢。可以考虑添加环境变量：
\`\`\`yaml
variables:
  GIT_DEPTH: "1" # 为1时代表只下载最近一次提交
\`\`\`
也可以在当前工程\`设置-CI/CD-流水线通用设置\`，\`流水线的GIT策略\`选择\`fetch\`（默认就是），\`Git 浅克隆\`的数量修改为\`1\`。

### 单元测试

\`Java\`项目请跳过。

对于\`Web\`项目，推荐在单元测试\`unit\`中，生成测试报告文件，再将它添加到\`cache\`路径，缓存起来，供下一任务分析使用。

如果你的测试框架使用的是\`jest\`，那么需要在\`coverageReporters\`中增加\`lcov\`，\`coverageDirectory\`建议设置为根目录下的\`coverage\`文件夹：

\`\`\`json
"coverageDirectory": "../coverage", // 相对路径，最终建议生成在根目录
"coverageReporters": [
  "text",
  "text-summary",
  "lcov",
],
\`\`\`

其它框架也类似。

如果没有这步配置，下面的静态扫描会无法生成单元测试覆盖率。

### 静态扫描

在以上2份范本中，\`static_scan\`是开启静态扫描的关键，对于\`java\`项目和一般\`web\`项目，使用的配置是不一样的，区别就是\`static_scan\`这个\`job\`，区别也不多，只有镜像\`image\`和\`script\`命令的参数不太一样。

假设你的任务运行成功了，那么在\`gitlab\`上\`CI/CD\`页面，打开\`static_scan\`这条流水线，可以看到以下日志信息：
\`\`\`log
INFO: Waiting for the analysis report to be processed (max 300s)
INFO: QUALITY GATE STATUS: PASSED - View details on https://sonar.udolphin.com/dashboard?id=test_dcv_auth_develop
INFO: Analysis total time: 48.303 s
\`\`\`

中间有个链接，它就是你的工程扫描后的页面，也就是我们的[\`SonarQube\`应用](https://sonar.udolphin.com/)，双击打开，使用\`gitlab\`账号登陆，就能看到扫描结果。

这里简单说明几处：

- 目前，\`gitlab\`上工程在\`SonarQube\`上对应的工程名称是\`gitlab\`路径（中间\`/\`转换为\`.\`）加\`.\`加分支名称，例如某工程路径是\`test/dcv/auth\`，当前分支是\`develop\`，那么对应的工程名称就变成\`test.dcv.auth.develop\`。

- \`SonarQube\`权限设置是按组划分的。比如用户\`小明\`属于组\`test/dcv\`，那么这个组内构建的工程，小明都有权限操作。如果小明不在这个组里，那他在\`SonarQube\`上是看不到这个组内工程的，如果中途加入，那他需要在\`SonarQube\`上退出重新登陆后才能看到。

- 重点关注\`Security Hotspots\`（安全热点）。如果后续提交的代码中有新的安全热点，那这个\`runner\`任务会宣告失败。

  如果对某个规则不满意，请在[这里](https://git.uino.com/book/gitbook/-/issues)提单，我们可以讨论是否禁用它。

更多精彩，等你发现。
`);
</script>
</body>
</html>
